/**
 * Project: topdt-jbpm
 * Copyright 2013  Top Digital Technology  Co. Ltd.
 * All right reserved.
 */
package com.topdt.jbpm.service;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.HibernateException;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.HistoryService;
import org.jbpm.api.NewDeployment;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskService;
import org.jbpm.api.model.ActivityCoordinates;
import org.jbpm.api.model.Transition;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.thx.common.spring.BeanFactory;
import com.thx.common.util.AppContext;
import com.topdt.jbpm.dao.ActivityDao;
import com.topdt.jbpm.dao.ActorDefinDetailDao;
import com.topdt.jbpm.dao.AppAuthorityDao;
import com.topdt.jbpm.dao.AppTypeDao;
import com.topdt.jbpm.dao.ApplicationDao;
import com.topdt.jbpm.dao.AttachmentDao;
import com.topdt.jbpm.dao.CommentDao;
import com.topdt.jbpm.dao.ControlDao;
import com.topdt.jbpm.dao.FieldDao;
import com.topdt.jbpm.dao.FlowDao;
import com.topdt.jbpm.dao.FlowDetailDao;
import com.topdt.jbpm.dao.FormDao;
import com.topdt.jbpm.dao.HistTodoDao;
import com.topdt.jbpm.dao.TodoDao;
import com.topdt.jbpm.dao.TodoVarDao;
import com.topdt.jbpm.dao.WorkDao;
import com.topdt.jbpm.dto.Props;
import com.topdt.jbpm.dto.Rect;
import com.topdt.jbpm.dto.Value;
import com.topdt.jbpm.form.Document;
import com.topdt.jbpm.form.FormHandle;
import com.topdt.jbpm.form.FormMenuDefin;
import com.topdt.jbpm.form.FormUI;
import com.topdt.jbpm.identity.ActorCalculator;
import com.topdt.jbpm.identity.IdFactory;
import com.topdt.jbpm.identity.IdentityService;
import com.topdt.jbpm.identity.User;
import com.topdt.jbpm.jpdl.draw.JpdlModel;
import com.topdt.jbpm.jpdl.draw.JpdlModelDrawer;
import com.topdt.jbpm.model.Activity;
import com.topdt.jbpm.model.ActorDefinDetail;
import com.topdt.jbpm.model.AppAuthority;
import com.topdt.jbpm.model.AppHandle;
import com.topdt.jbpm.model.AppType;
import com.topdt.jbpm.model.Application;
import com.topdt.jbpm.model.Control;
import com.topdt.jbpm.model.Flow;
import com.topdt.jbpm.model.FlowDetail;
import com.topdt.jbpm.model.Form;
import com.topdt.jbpm.model.HistTodo;
import com.topdt.jbpm.model.Todo;
import com.topdt.jbpm.model.TodoVar;
import com.topdt.jbpm.model.Work;
import com.topdt.jbpm.model.WorkOpinion;
import com.topdt.jbpm.service.cmd.Command;
import com.topdt.jbpm.service.cmd.GetPreTaskCmd;
import com.topdt.jbpm.service.cmd.GoBackWorkCmd;
import com.topdt.jbpm.service.cmd.GoOtherBackWorkCmd;
import com.topdt.jbpm.service.cmd.JumpResult;
import com.topdt.jbpm.service.cmd.RestartWorkCmd;
import com.topdt.jbpm.service.cmd.StartResult;
import com.topdt.jbpm.service.cmd.StartWorkCmd;
import com.topdt.jbpm.service.cmd.SubmitResult;
import com.topdt.jbpm.service.cmd.SubmitWorkCmd;
import com.topdt.jbpm.utils.ControlUtils;
import com.topdt.jbpm.utils.DecisionBranchUtil;
import com.topdt.jbpm.utils.ObjectUtils;
//import com.topdt.oa.attendance.dao.AttendworktypeDao;

/**
 * 建立日期 : 2013-4-10 下午7:39:41<br>
 * 作者 : balance<br>
 * 模块 : <br>
 * 描述 : <br>
 * 修改历史: 序号 日期 修改人 修改原因 <br>
 * 1 <br>
 * 2 <br>
 */
@Transactional(readOnly = true)
public class JbpmService {

	private ProcessEngine processEngine;

	private ExecutionService executionService;

	private TaskService taskService;

	private HistoryService historyService;

	private RepositoryService repositoryService;

	private ProcessDefinitionQuery processDefinitionQuery;

	@Autowired
	private ApplicationDao appDao;

	@Autowired
	private ActivityDao activityDao;

	@Autowired
	private ActorDefinDetailDao actorDefinDetailDao;

	@Autowired
	private ActorDefinDetailDao detailDao;

	@Autowired
	private FormDao formDao;

	@Autowired
	private TodoDao todoDao;

	@Autowired
	private TodoVarDao todoVarDao;

	@Autowired
	private WorkDao workDao;

	@Autowired
	private CommentDao commentDao;

	@Autowired
	private HistTodoDao histTodoDao;

	@Autowired
	private AppTypeDao appTypeDao;

	@Autowired
	private ControlDao controlDao;

	@Autowired
	private AttachmentDao attachmentDao;

	@Autowired
	private AppAuthorityDao appAuthorityDao;

	@Autowired
	private FlowDao flowDao;

	@Autowired
	private FlowDetailDao flowDetailDao;

	@Autowired
	private FieldDao fieldDao;

	private static Logger log = LoggerFactory.getLogger(JbpmService.class);

	public static JbpmService getJbpmService() {
		JbpmService service = (JbpmService) BeanFactory.getBean("jbpmService");
		return service;
	}

	private <T> T execute(Command<T> cmd) {
		return cmd.execute(this);
	}

	/*public List<Application> findAllApps() {
		return this.appDao.getAll();
	}*/

	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	@Resource(name = "processEngine")
	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
		if (this.processEngine != null) {
			this.executionService = processEngine.getExecutionService();
			this.historyService = processEngine.getHistoryService();
			this.repositoryService = processEngine.getRepositoryService();
			this.taskService = processEngine.getTaskService();
			this.processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
		}

	}

	/**
	 * 启动一个工作
	 *
	 * @param appId
	 *            应用Id
	 * @param starter
	 *            启动者Id
	 * @param vars
	 *            流程变量
	 */
	@Transactional(readOnly = false)
	public StartResult startWork(String appId, String starter, Map<String, Object> vars) {
		StartResult result = execute(new StartWorkCmd(appId, starter, vars));
		return result;
	}

	/**
	 * 提交工作
	 *
	 * @param todoId
	 */
	@Transactional(readOnly = false)
	public SubmitResult submitWork(String todoId, Document document, String outCome, Map<String, String> users, Map<String, Object> vars) {
		SubmitResult result = execute(new SubmitWorkCmd(todoId, document, outCome, users, vars));
		return result;
	}

	/**
	 * 退回
	 *
	 * @param todoId
	 */
	@Transactional(readOnly = false)
	public JumpResult goBackWork(String todoId) {
		JumpResult result = execute(new GoBackWorkCmd(todoId));
		return result;
	}


	/**
	 *  @Description    : 退回某个节点
	 *  @Method_Name    : goOtherBackWork
	 *  @param todoId
	 *  @return
	 *  @return         : JumpResult
	 *  @Creation Date  : 2015年1月5日 下午4:30:24
	 *  @version        : v1.00
	 *  @Author         : calonlan

	 *  @Update Date    :
	 *  @Update Author  :
	 */
	@Transactional(readOnly = false)
	public JumpResult goOtherBackWork(String todoId) {
		JumpResult result = execute(new GoOtherBackWorkCmd(todoId));
		return result;
	}

	/**
	 * 退回起草（重启工作）
	 *
	 * @param todoId
	 */
	@Transactional(readOnly = false)
	public JumpResult restartWork(String todoId) {
		JumpResult result = execute(new RestartWorkCmd(todoId));
		return result;
	}

	/**
	 * 获取可退回的环节
	 *
	 * @param todoId
	 * @return
	 */
	public JumpResult getPreTask(String todoId) {
		JumpResult result = execute(new GetPreTaskCmd(todoId));
		return result;
	}

	/*public Map<String, Object> autoSubmit(String todoId, Document document) {
		return null;
	}*/


	/**
	 *  @Description    : 获取节点的出口
	 *  @Method_Name    : getOutcomes
	 *  @param todoId
	 *  @return
	 *  @return         : OutComeResp
	 *  @Creation Date  : 2015年3月25日 上午10:16:46
	 *  @version        : v1.00
	 *  @Author         : balance

	 *  @Update Date    : 2015年3月25日 上午10:16:46
	 *  @Update Author  : calonlan
	 */
	public OutComeResp getOutcomes(String todoId) {

		Todo todo = todoDao.get(todoId);

		String taskId = todo.getTaskId();

		if (taskId == null) {

		} else {

			OutComeResp resp = null;

			Set<String> outComes = taskService.getOutcomes(taskId);
			/**
			 * 人工处理活动的出口路径若有多条，必然是多选一，不可能有多条并行的情况存在，所以：若outComes.size>1
			 * 一定是要返回界面让用户指定路径。
			 */
			if (outComes.size() > 1) {
				String checkedOutCome = "";
				TodoVar var = todoVarDao.getOutCome(todoId);
				if (var != null)
					checkedOutCome = var.getTextVal();

				if (resp == null)
					resp = new OutComeResp();

				for (String outCome : outComes) {

					if (outCome != null ) {
						String[] arr = outCome.split("_");
						//add by calonlan outCome属于回退某个节点
						if (arr.length > 1 && arr[1].equals("ht")) {
							resp.addOtherBackCome(outCome);
						//常规节点
						} else {
							resp.addOutCome(outCome, outCome.equals(checkedOutCome));
						}
					}
				}
			}

			resp = getBackCome(todo, resp, outComes);// 收集退回路径

			if (resp != null) {
				resp.setTodoId(todoId);
				return resp;
			} else {
				// 这种情况不必选择路径，会有零的情况吗？子任务就有可能是零
			}
		}
		return null;
	}

	/**
	 * @author balance 2014-11-24
	 * @param todo
	 * @param resp
	 * 获取退回上一步出口
	 */
	private OutComeResp getBackCome(Todo todo, OutComeResp resp, Set<String> outComes) {

		String activityName = todo.getActivityName();
		String workId = todo.getWorkId();
		Work work = workDao.get(workId);
		String flowId = work.getFlowId();
		Activity activity = activityDao.getActivityById(flowId, activityName);


		if ((activity.isBackable() || activity.isRestartable())) {
			if (resp == null)
				resp = new OutComeResp();
			String defaultCome=getDefaultCome(todo, outComes);
			if(StringUtils.isNotBlank(defaultCome)){
				resp.addDefaultCome(defaultCome);

			}
		}

		if (activity.isBackable())
			resp.addBackCome();

		if (activity.isRestartable())
			resp.addReStartCome();

		return resp;
	}


	/**
	 *  @Description    : 获取默认出口
	 *  @Method_Name    : getDefaultCome
	 *  @param todo
	 *  @param outComes
	 *  @return
	 *  @return         : String
	 *  @Creation Date  : 2015年3月25日 上午10:18:25
	 *  @version        : v1.00
	 *  @Author         :

	 *  @Update Date    : 2015年3月25日 上午10:18:25
	 *  @Update Author  : calonlan
	 */
	private String getDefaultCome(Todo todo, Set<String> outComes) {
		if (outComes.size() == 1) {
			TaskImpl task = (TaskImpl) taskService.getTask(todo.getTaskId());

			 ExecutionImpl exe = task.getExecution();

			 ProcessDefinitionImpl processDefin =  exe.getProcessDefinition();
			 ActivityImpl activity = processDefin.findActivity(task.getActivityName());

			List<? extends Transition> comes = activity.getOutgoingTransitions();
			String destName = "提交到下一环节";
			if (comes != null && comes.size() >= 1) {
				Transition to = comes.get(0);
				org.jbpm.api.model.Activity toActivity = to.getDestination();
				//TODO join的下一个节点目前认为是人工处理环节，如果有其它自动环节，需要递归处理
				if(toActivity.getType().equals("join")) {
					List<? extends Transition> out = toActivity.getOutgoingTransitions();
					toActivity = out.get(0).getDestination();
				}
				if(toActivity.getType().equals("end")) {
					destName = "结束流程";
				} else {
					destName = toActivity.getName();
				}
			}
			return destName;
		}
		return null;
	}

	public ActorResp getFutureActors(String todoId) {

		Todo todo = todoDao.get(todoId);

		String activityName = todo.getActivityName();

		ActorResp resp = null;

		Work work = workDao.get(todo.getWorkId());
		String flowId = work.getFlowId();

		// 从wf_task_actor 中找到需要在本活动指定人员的活动都有哪些
		List<Activity> activities = activityDao.getActivityByAssigner(flowId, activityName);

		String outCome = getOutcomesOfTodo(todoId);

		if (activities.size() > 0) {
			resp = new ActorResp();
			resp.setTodoId(todoId);

			String taskId = todo.getTaskId();
			Context context = null;
			if (taskId != null) {
				Object obj = this.taskService.getVariable(taskId, Context.KEY);
				if (obj != null)
					context = (Context) obj;
			}

			ProcessDefinitionImpl processDefin = null;

			if (outCome != null) {//outCome不为空，说明本环节出口需要选择路径的
				TaskImpl task = (TaskImpl) taskService.getTask(todo.getTaskId());
				TaskImpl superTask = task.getSuperTask();
				if (superTask != null)
					task = superTask;
				processDefin = task.getProcessInstance().getProcessDefinition();
			}

			//决定节点关于选择处理人工具类  add by calonlan
			DecisionBranchUtil branchUtil = new DecisionBranchUtil();

			for (Activity defin : activities) {//
				String actName = defin.getActivityName();
				ActivityImpl act = null;
				if (outCome != null && processDefin != null) {//若路径已经确定，只给选定路径后面的节点选人
					act = processDefin.findActivity(actName);
					List<? extends Transition> transitions = act.getIncomingTransitions();
					for (Transition t : transitions) {
						String tName = t.getName();
						if (tName != null && tName.equals(outCome)) {
							List<User> actors = ActorCalculator.calculate(defin, context, todo.getToUserId());
							resp.addSetting(defin.getActivityName(), defin.getActorNUM(), actors);
							break;
						}
					}
				} else {
					//正常节点
					if(defin.getDesc() == null || defin.getDesc().length()<=0) {
						List<User> actors = ActorCalculator.calculate(defin, context, todo.getToUserId());
						resp.addSetting(defin.getActivityName(), defin.getActorNUM(), actors);
						//选择人的节点是决定节点的下一个节点,只选根据业务规则自动判断要走的分支的人. add by calonlan
					} else {
						boolean result = branchUtil.isBranchMatch(defin, context);
						if(result) {
							List<User> actors = ActorCalculator.calculate(defin, context, todo.getToUserId());
							resp.addSetting(defin.getActivityName(), defin.getActorNUM(), actors);

						}
					}

				}
			}
		}

		if (resp == null || resp.getSettings() == null || resp.getSettings().size() == 0)
			resp = null;
		return resp;
	}


	/**
	 *  @Description    : 保存"待办变量"
	 *  @Method_Name    : saveActorForTodo
	 *  @param todoId
	 *  @param receivedActors
	 *  @return         : void
	 *  @Creation Date  : 2015年3月25日 上午10:19:36
	 *  @version        : v1.00
	 *  @Author         :

	 *  @Update Date    : 2015年3月25日 上午10:19:36
	 *  @Update Author  : calonlan
	 */
	@Transactional(readOnly = false)
	public void saveActorForTodo(String todoId, String receivedActors) {
		Todo todo = todoDao.get(todoId);
		todoVarDao.delActor(todoId);
		TodoVar var = new TodoVar();
		var.setTodoId(todoId);
		var.setVarType(TodoVar.TYPE_ACTOR);
		var.setTextVal(receivedActors);
		var.setWorkId(todo.getWorkId());
		var.setCompanyId(todo.getCompanyId());
		todoVarDao.save(var);
	}

	public String getOutcomesOfTodo(String todoId) {
		TodoVar var = todoVarDao.getOutCome(todoId);
		if (var == null)
			return null;
		return var.getTextVal();
	}

	@Transactional(readOnly = false)
	public void saveOutComeForTodo(String todoId, String outCome) {

		Todo todo = todoDao.get(todoId);
		todoVarDao.delOutCome(todoId);

		TodoVar var = new TodoVar();
		var.setTodoId(todoId);
		var.setVarType(TodoVar.TYPE_OUTCOME);
		var.setTextVal(outCome);
		var.setWorkId(todo.getWorkId());
		var.setCompanyId(todo.getCompanyId());
		todoVarDao.save(var);
	}

	/**
	 * 取得人员某个工作的待办
	 *
	 * @param workId
	 * @param userId
	 * @return
	 */
	public Todo findTodoByWorkAndUser(String workId, String userId) {
		return todoDao.findTodoByWorkAndUser(workId, userId);
	}

	/**
	 * 取得给定用户可以处理的待办
	 *
	 * @param userId
	 * @return
	 */
	public List<Todo> findReadyTodo(String userId) {
		return findTodo(userId, Todo.STATE_READY);
	}

	/**
	 * 取得给定用户需要抢占的待办
	 *
	 * @param userId
	 * @return
	 */
	public List<Todo> findCompetitiveTodo(String userId) {
		return findTodo(userId, Todo.STATE_COMPETITIVE);
	}

	private List<Todo> findTodo(String userId, String todoState) {
		List<Todo> todos = this.todoDao.getTodosByState(userId, todoState);
		return todos;
	}

	/**
	 * 取到给定用户的所有待办
	 *
	 * @param userId
	 * @return
	 */
	/*public List<Todo> findAllTodo(String userId) {
		List<Todo> todos = this.todoDao.getAllTodos(userId);
		return todos;
	}
*/
	@Transactional(readOnly = false)
	public void takeTodo(String todoId) {

		Todo todo = todoDao.get(todoId);
		todo.setState(Todo.STATE_READY);
		todoDao.deleteOthers(todo.getWorkId(), todoId);
		todoDao.update(todo);

		Work work = this.workDao.get(todo.getWorkId());
		IdentityService idService = IdFactory.getIdentityServiceFactory().getIdentityService();
		String curActivityName = "【" + todo.getActivityName() + ":" + idService.getUserByUserId(todo.getToUserId()).getName() + "】";
		work.setCurActivityName(curActivityName);
		this.workDao.update(work);
		this.taskService.takeTask(todo.getTaskId(), todo.getToUserId());
	}

	public Todo getTodoById(String todoId) {

		Todo todo = todoDao.get(todoId);

		return todo;
	}

	/**
	 * 装配表单
	 *
	 * @param appId
	 * @param workId
	 * @param activity
	 * @param userId
	 * @return
	 */
	public FormUI assembleForm(String appId, String workId, String activity, String userId, boolean isMobile) {

		Application app = this.appDao.get(appId);

		AppHandle handle = app.getHandle();

		String javaClass = handle.getHandleJava();

		Object obj = ObjectUtils.getInstance(javaClass);

		if (obj == null) {

		} else {
			FormHandle assembler = (FormHandle) obj;
			log.info("\n组装web端表单开始.....\n");
			Map<String, Object> context = new HashMap<String, Object>();
			if (isMobile) {
				context.put("isMobile", true);
				context.put("userId", userId);
			}
			context.put("canAutoDelete", "true");
			return assembler.assemble(app, workId, activity, userId, context);
		}
		return null;
	}

	/**
	 * 保存表单
	 *
	 * @return
	 */
	@Transactional(readOnly = false)
	public Document saveForm(String workId, Map<String, String[]> parameter, String todoId) {
		Work work = this.workDao.get(workId);

		Application app = this.appDao.get(work.getAppId());

		AppHandle handle = app.getHandle();

		String javaClass = handle.getHandleJava();

		Object obj = ObjectUtils.getInstance(javaClass);

		if (obj != null) {
			FormHandle assembler = (FormHandle) obj;
			boolean canSave = false;
			if (todoId != null && !"".equals(todoId) && !work.isFreeFlow()) {
				Todo todo = this.todoDao.get(todoId);
				if (!hasOperateAuthorityForTodo(app, work, todo, "save")) {
					return assembler.getDocument(workId);
				} else {
					canSave = true;
				}
			}
			if (!canSave && !work.getWorkState().equals(Work.STATE_START)) {
				return assembler.getDocument(workId);
			}
			String workTitle = parameter.get("workTitle")[0];

//			if (!app.getAppName().equals(workTitle.trim())) {
			if(StringUtils.isNotBlank(workTitle.trim())){//liujie edit 20151230 不晓得为啥和应用名称一样就不保存了
				work.setWorkTitle(workTitle);
				this.workDao.update(work);
			}
			Document doc = assembler.convert2Doc(parameter);
			return assembler.saveForm(workId, doc);
		}
		return null;
	}

	/**
	 * 列出starter的所有起草工作
	 *
	 * @param starter
	 * @return
	 */
	public List<Work> findWork(String starter, String state) {
		return this.workDao.listWork(starter, state);
	}

	public FormUI getWorkForm(String todoId, boolean isMobile) {

		Todo todo = this.todoDao.get(todoId);

		Work work = this.workDao.get(todo.getWorkId());

		Application app = this.appDao.get(work.getAppId());

		AppHandle handle = app.getHandle();

		String javaClass = handle.getHandleJava();

		Object obj = ObjectUtils.getInstance(javaClass);
		if (obj != null) {
			FormHandle assembler = (FormHandle) obj;

			Map<String, Object> context = new HashMap<String, Object>();
			context.put("todoId", todoId);
			context.put("canAutoDelete", "false");
			context.put("activityName", todo.getActivityName());//--zili   用于显示还未保存至数据库的默认意见。
			if (isMobile) {
				context.put("isMobile", true);
				context.put("userId", todo.getToUserId());
			}
			if (todo.getState().equals(Todo.STATE_COMPETITIVE))
				context.put("preempt", "preempt-show");
			return assembler.assemble(app, work.getWorkId(), todo.getActivityName(), null, context);

		}
		return null;
	}

	public FormUI getWorkForm(String workId, String userId, boolean isMobile) {

		Todo todo = findTodoByWorkAndUser(workId, userId);

		if (todo != null) {
			return getWorkForm(todo.getTodoId(), isMobile);
		} else {
			Work work = this.workDao.get(workId);

			Application app = this.appDao.get(work.getAppId());

			AppHandle handle = app.getHandle();

			String javaClass = handle.getHandleJava();

			Object obj = ObjectUtils.getInstance(javaClass);
			if (obj != null) {
				FormHandle assembler = (FormHandle) obj;
				Map<String, Object> context = new HashMap<String, Object>();
				if (isMobile) {
					context.put("isMobile", true);
					context.put("userId", userId);
				}
				//自由流程待办已经提交的标识
				context.put("isFreeSubmit", true);
				/*context.put("canAutoDelete", "false");
				context.put("save", "none");
				context.put("complete", "none");
				context.put("delete", "none");
				context.put("attach", "none");
				context.put("opinion", "none");
				context.put("back", "none");
				context.put("publish", "none");
				context.put("archives", "none");
				context.put("workDefaultTitle", "readonly");
				String appAttr = app.getAppAttr();
				if (appAttr.equals(Application.APPATTR_DOC)
						|| appAttr.equals(Application.APPATTR_CUSTOM_DOC)
						|| appAttr.equals(Application.APPATTR_CUSTOM_DOC_OPINION))
					context.put("docControl", "000");*/
				return assembler.assemble(app, work.getWorkId(), null, null, context);

			}
			return null;
		}
	}

	// --列出所有的appType
	public List<AppType> findAllAppType() {
		return this.appTypeDao.getAllByComId();
	}

	/*public List<Application> findAppsByType(AppType type) {
		return this.appDao.findAppsByType(type);
	}*/

	public InputStream getFlowImageIs(String workId) {
		Work work = this.workDao.get(workId);
		String flowId = work.getFlowId();
		ProcessDefinition processDefinition = processDefinitionQuery.processDefinitionId(flowId).uniqueResult();
		String pngFileName = processDefinition.getImageResourceName();
		InputStream is = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), pngFileName);
		return is;
	}

	public List<ActivityCoordinates> getActivityCoordinates(String workId) {
		List<ActivityCoordinates> acs = new ArrayList<ActivityCoordinates>();
		Work work = this.workDao.get(workId);
		if (work.getWorkState().equals(Work.STATE_END)) {
			ActivityCoordinates ac = repositoryService.getActivityCoordinates(work.getFlowId(), "end");
			acs.add(ac);
		} else {
			List<String> activityNames = this.todoDao.getActivityNamesByworkId(workId);
			for (String activityName : activityNames) {
				ActivityCoordinates ac = repositoryService.getActivityCoordinates(work.getFlowId(), activityName);
				acs.add(ac);
			}
		}
		return acs;
	}

	@Transactional(readOnly = false)
	public String deleteWorkFalse(String workId, String userId) {
		String message = "";
		// --1.判断work是否在草稿状态
		Work work = this.workDao.get(workId);
		if (work.getWorkState().equals(Work.STATE_START) && work.getStarter().equals(userId)) {
			// --是草稿且是当前登录者起草的可以删除
			// --2.删除工作的待办和待办的todoVar
			Todo todo = this.todoDao.findTodoByWorkAndUser(workId, userId);
			if (todo != null) {
				this.todoDao.delete(todo.getTodoId());
				HistTodo hTodo = new HistTodo(todo);
				hTodo.setState(Work.STATE_DELETE);
				hTodo.setFinishTime(new Date());
				this.histTodoDao.save(hTodo);
			}
			work.setWorkState(Work.STATE_DELETE);
			this.workDao.update(work);
			message = "删除成功！";
		} else {
			message = "工作已提交！不能删除！";
		}

		return message;
	}

	@Transactional(readOnly = false)
	public String deleteWork(String workId, String userId) {
		String message = "";
		Work work = this.workDao.get(workId);
		if (work.getWorkState().equals(Work.STATE_START) && work.getStarter().equals(userId)) {
			deleteWorkTrue(work);
			message = "删除成功！";
		} else {
			message = "工作已提交！不能删除！";
		}
		return message;
	}

	private void deleteWorkTrue(Work work) {

		String workId = work.getWorkId();

		Application app = appDao.get(work.getAppId());

		AppHandle handleM = app.getHandle();

		String javaClass = handleM.getHandleJava();

		Object obj = ObjectUtils.getInstance(javaClass);

		if (obj == null) {

		} else {
			FormHandle handle = (FormHandle) obj;
			handle.deleteDoc(workId);
		}
		attachmentDao.delByWorkId(workId);
		workDao.delete(workId);
		todoDao.delByWorkId(workId);
		todoVarDao.delByWorkId(workId);
		histTodoDao.delByWorkId(workId);
		commentDao.delByWorkId(workId);

		deleteJbpmWork(workId);
	}

	@Transactional(readOnly = false)
	public void deleteJbpmWork(String workId) {
		ProcessInstance pi = executionService.createProcessInstanceQuery().processInstanceKey(workId).uniqueResult();
		if (pi != null)
			this.executionService.deleteProcessInstanceCascade(pi.getId());
	}

	/**
	 * 查询公文应用列表
	 */
	public List<Application> listDocumentApps() {

		return this.appDao.listDocumentApps();
	}

	/**
	 * 查找已办(起草)流转日志
	 */
	public List<HistTodo> findWorkRecordFromHistTodo(String workId) {
		List<HistTodo> list = histTodoDao.findWorkRecordFromHistTodo(workId);
		return list;
	}

	/**
	 * 查找待办流转日志
	 */
	public List<Todo> findWorkRecordFromTodo(String workId) {
		List<Todo> list = todoDao.findWorkRecordFromTodo(workId);
		return list;
	}

	@Transactional(readOnly = false)
	public ProcessDefinition deploy(ProcessResource... resource) {

		NewDeployment deployment = repositoryService.createDeployment();
		for (ProcessResource r : resource) {

			if (r != null && r.getInputStream() != null)
				deployment.addResourceFromInputStream(r.getName(), r.getInputStream());
		}
		String deploymentId = deployment.deploy();
		ProcessDefinition defin = null;
		if (repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).list() != null
				&& repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).list().size() > 0) {
			defin = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).list().get(0);
		}
		return defin;
	}

	public ProcessResource getProcessImag(ProcessResource resource) {

		String name = resource.getName();

		InputStream input = resource.getInputStream();

		try {

			JpdlModel jpdlModel = new JpdlModel(input);
			BufferedImage imag = new JpdlModelDrawer().draw(jpdlModel);

			ByteArrayOutputStream bs = new ByteArrayOutputStream();

			ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);

			ImageIO.write(imag, "png", imOut); // scaledImage1为BufferedImage，jpg为图像的类型

			InputStream is = new ByteArrayInputStream(bs.toByteArray());

			ProcessResource imagRes = new ProcessResource();
			imagRes.setName(name.substring(0, name.indexOf(".")) + ".png");
			imagRes.setInputStream(is);
			return imagRes;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;

	}

	public Flow getFlowByFlowId(String flowId) {
		return this.flowDao.getById(flowId);
	}


	public FlowDetail getDetailByFlowId(String flowId) {
		return this.flowDetailDao.getDetailById(flowId);
	}

	public Flow getFlowByFlowName(String flowName) {
//		return this.flowDao.getFlowByFlowName(flowName);
		return null;
	}

	public FlowDetail findFlowDetailByDetailId(String detailId) {
		return this.flowDetailDao.findById(detailId);
	}
/*
	public List<Activity> findActivityByDetailId(String flowDetailId) {
		return this.activityDao.findByFlowDetailId(flowDetailId);
	}*/

	/*@Transactional(readOnly = false)
	public void delFlowDetail(String detailId) {
		this.flowDetailDao.delete(detailId);
	}*/

	/*@Transactional(readOnly = false)
	public void delActivity(String activityId) {
		this.activityDao.delete(activityId);
	}*/
/*
	@Transactional(readOnly = false)
	public void delActivityDefinDetail(String activityId) {
		List<ActorDefinDetail> list = this.actorDefinDetailDao.findByActivityId(activityId);
		if (list != null && list.size() > 0) {
			for (ActorDefinDetail actorDefinDetail : list) {
				this.actorDefinDetailDao.delete(actorDefinDetail.getDetailId());
			}
		}
	}*/

	/*@Transactional(readOnly = false)
	public void delFlow(String flowId) {
		this.flowDao.delete(flowId);
	}*/

	@Transactional(readOnly = false)
	public void delJbpmFlow(String flowId) {
		ProcessDefinition processDefinition = this.repositoryService.createProcessDefinitionQuery().processDefinitionId(flowId).uniqueResult();
		String deploymentId = processDefinition.getDeploymentId();
		repositoryService.deleteDeployment(deploymentId);
	}


	/**
	 * 删除工作流下的某个版本的工作信息
	 *
	 * @param flowDetail
	 */
	@Transactional(readOnly = false)
	public void delFlowDetail(FlowDetail flowDetail) {
		List<Activity> activities = activityDao.findByFlowDetailId(flowDetail.getDetailId());
		if (activities != null && activities.size() > 0) {
			for (Activity activity : activities) {
				//删除活动处理人
				actorDefinDetailDao.delByActivityId(activity.getActivityId());
				//删除活动
				activityDao.delete(activity.getActivityId());
			}
		}
		//删除流程详细
		flowDetailDao.delete(flowDetail.getDetailId());
	}

	/**
	 * 删除工作流
	 *
	 * @param listFlowDetail
	 * @param flowId
	 */
	@Transactional(readOnly = false)
	public void delWorkStream(List<FlowDetail> listFlowDetail, String flowId) {
		String jbpmFlowId = "";
		int i = 0;
		try {
			for (FlowDetail flowDetail : listFlowDetail) {
				jbpmFlowId = flowDetail.getJbpmFlowId();
				if ("1".equals(flowDetail.getState())) {
					i += 1;
				}
				delFlowDetail(flowDetail);
			}
			if (i > 0) {
				delJbpmFlow(jbpmFlowId);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*public List<Field> getFieldByFormId(String formId) {
		return this.fieldDao.getFieldsByformId(formId);
	}*/

	/**
	 * 保存application实体
	 *
	 * @param app
	 */
	/*@Transactional(readOnly = false)
	public void saveApp(Application app) {
		this.appDao.save(app);
	}*/

	/**
	 * 保存form实体
	 *
	 * @param form
	 */
	/*@Transactional(readOnly = false)
	public void saveForm(Form form) {
		this.formDao.save(form);
	}*/

	/**
	 * 保存field实体
	 *
	 * @param field
	 */
	/*@Transactional(readOnly = false)
	public void saveField(Field field) {
		this.fieldDao.save(field);
	}*/

	/**
	 * 保存flow实体
	 *
	 * @param flow
	 */
	/*@Transactional(readOnly = false)
	public void saveFlow(Flow flow) {
		this.flowDao.save(flow);
	}*/

	/**
	 * 保存flowDetail实体
	 *
	 * @param flowDetail
	 */
	/*@Transactional(readOnly = false)
	public void saveFlowDetail(FlowDetail flowDetail) {
		this.flowDetailDao.save(flowDetail);
	}*/

	/**
	 * 保存activity实体
	 *
	 * @param activity
	 */
	/*@Transactional(readOnly = false)
	public void saveActivity(Activity activity) {
		this.activityDao.save(activity);
	}*/

	/**
	 * 保存actorDefinDetail实体
	 *
	 * @param actorDefinDetail
	 */
	/*@Transactional(readOnly = false)
	public void saveActorDefinDetail(ActorDefinDetail actorDefinDetail) {
		this.actorDefinDetailDao.save(actorDefinDetail);
	}*/

	/**
	 * 根据appId获取app对象
	 *
	 * @param appId
	 * @return
	 */
	/*public Application getAppByAppId(String appId) {
		return this.appDao.getById(appId);
	}*/

	/**
	 * 初始化数据
	 *
	 * @param companyId
	 * @throws Exception
	 */
	@Transactional(readOnly = false)
	public void initData(String companyId) {
		try {
			this.appDao.addApp(companyId);
			this.formDao.addForm(companyId);
			this.fieldDao.addField(companyId);
			this.flowDao.addFlow(companyId);
			this.flowDetailDao.addFlowDetail(companyId);
			this.activityDao.addActivity(companyId);
			this.actorDefinDetailDao.addActorDefinDetail(companyId);
//			this.attendworktypeDao.addAttendWorkType(companyId);
			this.appTypeDao.addAppType(companyId);
		} catch (HibernateException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 保存数据到数据库
	 *
	 * @param map
	 * @param list
	 * @param listProps
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param flowId
	 */
	@Transactional(readOnly = false)
	public String save(List<Rect> list, List<Props> listProps, String jbpmFlowId, String jbpmFlowKey, String detailId, String json, byte[] xml) {
		// 1先获取flowDetail实体，判断是否是空，
		FlowDetail flowDetail = this.flowDetailDao.findById(detailId);
		if (flowDetail != null) {
			// 更新该流程
			if ("1".equals(flowDetail.getState())) {
				// 添加3张表
				// 获取flowId
				String flowId = flowDetail.getFlowId();
				// 1修改flow
				saveOrUpdateFlow(jbpmFlowId, jbpmFlowKey, flowId, listProps);
				// 2添加flowDetail
				String flowDetailId = saveFlowDetail(flowId, jbpmFlowId, jbpmFlowKey, json, xml);
				// 3添加activity
				List<String> listActivityId = saveActivity(list, flowDetailId, listProps, jbpmFlowId, jbpmFlowKey);
				// 4添加activityDetail
				saveActivityDetail(null, listActivityId, list);

				return flowDetail.getDetailId();
			} else {
				// 更新表
				// 1获取flowId
				String flowId = flowDetail.getFlowId();
				// 1修改flow
				saveOrUpdateFlow(jbpmFlowId, jbpmFlowKey, flowId, listProps);
				// 2修改flowDetail
				saveOrUpdateFlowDetail(flowDetail, flowId, jbpmFlowId, jbpmFlowKey, json, xml);
				// 3修改activity
				List<Activity> listActivity = this.activityDao.findByFlowDetailId(detailId);
				List<String> listString = new ArrayList<String>();
				if (listActivity != null && listActivity.size() > 0) {
					for (int i = 0; i < listActivity.size(); i++) {
						listString.add(listActivity.get(i).getActivityId());
						this.activityDao.delete(listActivity.get(i).getActivityId());
					}
				}
				List<String> listActivityId = saveActivity(list, detailId, listProps, jbpmFlowId, jbpmFlowKey);
				// 4修改activityDetail
				saveActivityDetail(listString, listActivityId, list);

				return flowDetail.getDetailId();
			}
		} else {
			// 添加 该流程
			// 1先添加流程flow
			String flowIdNew = saveFlow(jbpmFlowId, jbpmFlowKey, listProps);
			// 2添加flowDetail
			String flowDetailId = saveFlowDetail(flowIdNew, jbpmFlowId, jbpmFlowKey, json, xml);
			// 3添加activity
			List<String> listActivityId = saveActivity(list, flowDetailId, listProps, jbpmFlowId, jbpmFlowKey);
			// 4添加activityDetail
			saveActivityDetail(null, listActivityId, list);
			return flowDetailId;
		}
	}

	/**
	 * 保存数据到activity_detail表中
	 *
	 * @param listString
	 * @param listActivityId
	 * @param list
	 */
	private void saveActivityDetail(List<String> listString, List<String> listActivityId, List<Rect> list) {//
		if (listString != null && listString.size() > 0) {
			for (int i = 0; i < listString.size(); i++) {
				List<ActorDefinDetail> listADDetail = this.detailDao.findByActivityId(listString.get(i));
				if (listADDetail != null && !"".equals(listADDetail) && listADDetail.size() > 0) {
					for (int j = 0; j < listADDetail.size(); j++) {
						this.detailDao.delete(listADDetail.get(j).getDetailId());
					}
				}
			}
		}
		if (listActivityId != null && listActivityId.size() > 0 && list != null && !"".equals(list)) {
			String comId = AppContext.getCurrentComId();
			for (int i = 0; i < listActivityId.size(); i++) {
				Activity activity = this.activityDao.getById(listActivityId.get(i));
				if (activity != null && !"".equals(activity)) {
					for (int j = 0; j < list.size(); j++) {
						if (activity.getActivityName().equals(list.get(j).getProps().getText().getValue())) {
							Value assignee = list.get(j).getProps().getAssignee();
							if (assignee != null) {
								String value = assignee.getValue();
								if (value != null && !"".equals(value)) {
									String[] s = value.split(";");
									for (int k = 0; k < s.length; k++) {
										String[] act = s[k].split(":");
										if (act != null && act.length > 0) {
											ActorDefinDetail adDetail = new ActorDefinDetail();
											adDetail.setActorType(Integer.parseInt(act[0]));
											if (act.length == 2) {
												adDetail.setActors(act[1]);
											}
											adDetail.setActivityId(listActivityId.get(i));
											adDetail.setCompanyId(comId);
											this.detailDao.save(adDetail);

										}
									}
								}
							}

							continue;
						}
					}
				}
			}
		}
	}

	/**
	 * 保存数据到activity表中
	 *
	 * @param list
	 * @param flowDetailId
	 * @param listProps
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @return
	 */
	private List<String> saveActivity(List<Rect> list, String flowDetailId, List<Props> listProps, String jbpmFlowId, String jbpmFlowKey) {
		List<String> listActivityId = new ArrayList<String>();
		if (list != null && list.size() > 0) {
			String comId = AppContext.getCurrentComId();
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i) != null) {
					if (!"start".equals(list.get(i).getType()) && !"end".equals(list.get(i).getType()) && !"fork".equals(list.get(i).getType())
							&& !"join".equals(list.get(i).getType()) &&! "loopjoin".equals(list.get(i).getType())
							&& !"foreach".equals(list.get(i).getType()) &&! "decision".equals(list.get(i).getType())) {
						Activity activity = new Activity();
						activity.setFlowId(jbpmFlowId);
						activity.setFlowKey(jbpmFlowKey);
						String activityName = list.get(i).getProps().getText().getValue();
						// 环节顺序
						String seqNUM = list.get(i).getProps().getTemp1().getValue();
						String condition = list.get(i).getProps().getCondition().getValue();
						if (list.get(i).getProps().getAssignee() != null && !"".equals(list.get(i).getProps().getAssignee())) {
							int actorNUM = list.get(i).getProps().getAssignee().getActorNum();
							String doRule = list.get(i).getProps().getAssignee().getDoRule();
							String assignerActivity = list.get(i).getProps().getAssignee().getAssignerActivity();
							String actorModel = list.get(i).getProps().getAssignee().getActorModel();
							activity.setActorNUM(actorNUM);
							activity.setDoRule(doRule);
							activity.setAssignerActivity(assignerActivity);
							activity.setActorModel(actorModel);
						}
						if (StringUtils.isNotBlank(seqNUM)) {
							activity.setSeqNUM(Integer.valueOf(seqNUM));
						} else {
							activity.setSeqNUM(i);
						}

						//设置可退回，可退回起草zhangyong20141126
						String temp2 = list.get(i).getProps().getTemp2().getValue();
						String temp3 = list.get(i).getProps().getTemp3().getValue();
						activity.setBackable(temp2.equals("1"));
						activity.setRestartable(temp3.equals("1"));

						activity.setActivityName(activityName);
						activity.setFlowDetailId(flowDetailId);
						activity.setCompanyId(comId);

						//设置activiti 节点描述
						activity.setDesc(condition);
						this.activityDao.save(activity);
						listActivityId.add(activity.getActivityId());
					}
				}
			}
		}
		return listActivityId;
	}

	/**
	 * 更新flow表中的数据
	 *
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param flowId
	 * @param listProps
	 * @return
	 */
	public String saveOrUpdateFlow(String jbpmFlowId, String jbpmFlowKey, String flowId, List<Props> listProps) {
		Flow flow = this.flowDao.getById(flowId);
		if (listProps != null && listProps.size() > 0) {
			flow.setFlowName(listProps.get(0).getName().getValue());
		}
		flow.setCreatTime(new Date());
		flow.setFlowId(flowId);
		flowDao.saveOrUpdate(flow);
		String flowIdNew = flow.getFlowId();
		return flowIdNew;
	}

	/**
	 * 保存数据到flow表中
	 *
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param listProps
	 * @return
	 */
	public String saveFlow(String jbpmFlowId, String jbpmFlowKey, List<Props> listProps) {
		String flowIdNew = "";
		if (listProps != null && listProps.size() > 0) {
			String comId = AppContext.getCurrentComId();
			for (int i = 0; i < listProps.size(); i++) {
				Flow flow = new Flow();
				flow.setCompanyId(comId);
				flow.setJbpmFlowId(jbpmFlowId);
				flow.setJbpmFlowKey(jbpmFlowKey);
				flow.setCreatTime(new Date());
				flow.setFlowName(listProps.get(i).getName().getValue());
				flow.setIsInherent("0");
				flowDao.save(flow);
				flowIdNew = flow.getFlowId();
			}
		}
		return flowIdNew;
	}

	/**
	 * 更新数据到flow_detail表中
	 *
	 * @param flowDetail
	 * @param flowIdNew
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param json
	 * @param xml
	 * @return
	 */
	private String saveOrUpdateFlowDetail(FlowDetail flowDetail, String flowIdNew, String jbpmFlowId, String jbpmFlowKey, String json, byte[] xml) {
		flowDetail.setCreateTime(new Date());
		try {
			flowDetail.setJson(json.getBytes("utf-8"));
		} catch (UnsupportedEncodingException e) {
			flowDetail.setJson(json.getBytes());
			e.printStackTrace();
		}
		flowDetail.setXml(xml);
		// 已发布的流程修改应该执行的代码
		// String version =
		// this.flowDetailDao.findMaxNum(flowDetail.getFlowId());
		// flowDetail.setVersion(Integer.parseInt(version)+1+"");
		// 修改不必更新version
		flowDetail.setDetailId(flowDetail.getDetailId());
		this.flowDetailDao.saveOrUpdate(flowDetail);
		String flowDetailId = flowDetail.getDetailId();
		return flowDetailId;
	}

	/**
	 * 保存数据到flow_detail表中
	 *
	 * @param flowIdNew
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param json
	 * @param xml
	 * @return
	 */
	private String saveFlowDetail(String flowIdNew, String jbpmFlowId, String jbpmFlowKey, String json, byte[] xml) {
		String flowDetailId = "";
		FlowDetail flowDetail = new FlowDetail();
		String comId = AppContext.getCurrentComId();
		flowDetail.setCompanyId(comId);
		flowDetail.setCreateTime(new Date());
		flowDetail.setJbpmFlowId(jbpmFlowId);
		flowDetail.setJbpmFlowKey(jbpmFlowKey);
		flowDetail.setState("0");
		try {
			flowDetail.setJson(json.getBytes("utf-8"));
		} catch (UnsupportedEncodingException e) {
			flowDetail.setJson(json.getBytes());
			e.printStackTrace();
		}
		flowDetail.setXml(xml);
		flowDetail.setFlowId(flowIdNew);
		String version = this.flowDetailDao.findMaxNum(flowDetail.getFlowId());
		flowDetail.setVersion(Integer.parseInt(version) + 1 + "");
		this.flowDetailDao.save(flowDetail);
		flowDetailId = flowDetail.getDetailId();
		return flowDetailId;
	}

	/**
	 * 更新数据库里的jbpmFlowId , jbpmFlowKey字段
	 *
	 * @param jbpmFlowId
	 * @param jbpmFlowKey
	 * @param flow
	 * @param flowDetail
	 */
	@Transactional(readOnly = false)
	public void update(String jbpmFlowId, String jbpmFlowKey, Flow flow, FlowDetail flowDetail) {
		updateFlow(jbpmFlowId, jbpmFlowKey, flow);
		updateFlowDetail(jbpmFlowId, jbpmFlowKey, flowDetail);
		updateActivity(jbpmFlowId, jbpmFlowKey, flowDetail);
	}

	private void updateActivity(String jbpmFlowId, String jbpmFlowKey, FlowDetail flowDetail) {
		List<Activity> listActivity = this.activityDao.findByFlowDetailId(flowDetail.getDetailId());
		if (listActivity != null && listActivity.size() > 0) {
			for (Activity activity : listActivity) {
				activity.setActivityId(activity.getActivityId());
				activity.setFlowId(jbpmFlowId);
				activity.setFlowKey(jbpmFlowKey);
				this.activityDao.saveOrUpdate(activity);
			}
		}
	}

	private void updateFlowDetail(String jbpmFlowId, String jbpmFlowKey, FlowDetail flowDetail) {
		flowDetail.setDetailId(flowDetail.getDetailId());
		flowDetail.setState("1");
		flowDetail.setJbpmFlowId(jbpmFlowId);
		flowDetail.setJbpmFlowKey(jbpmFlowKey);
		this.flowDetailDao.saveOrUpdate(flowDetail);
	}

	private void updateFlow(String jbpmFlowId, String jbpmFlowKey, Flow flow) {
		flow.setFlowId(flow.getFlowId());
		flow.setJbpmFlowId(jbpmFlowId);
		flow.setJbpmFlowKey(jbpmFlowKey);
		this.flowDao.saveOrUpdate(flow);
	}

	public FormUI getWorkFormView(String workId, boolean isPrint) {
		Work work = this.workDao.get(workId);

		Application app = this.appDao.get(work.getAppId());

		AppHandle handle = app.getHandle();

		String javaClass = handle.getHandleJava();

		Object obj = ObjectUtils.getInstance(javaClass);

		if (obj != null) {
			FormHandle assembler = (FormHandle) obj;
			Map<String, Object> context = new HashMap<String, Object>();
			context.put("isPrint", "" + isPrint);
			context.put("isView", true);
			return assembler.assemble(app, workId, null, null, context);
		}
		return null;
	}

	/**
	 * 判断是否存在 流程 建立日期 : Sep 23, 2013 5:23:14 PM<br>
	 * 作者: 孙耀飞<br>
	 * 模块: <br>
	 * 描述: 保存流程定义的时候<br>
	 * 1 <br>
	 * 2 <br>
	 */
	public String checkFlowName(String detailId, String flowName) {
		FlowDetail flowDetail = this.flowDetailDao.findById(detailId);
		Flow flowByName = this.getFlowByFlowName(flowName);
		if (flowDetail != null) {
			Flow flow = this.flowDao.getById(flowDetail.getFlowId());
			if (flow != null) {
				if (flow.getFlowName().equals(flowName)) {
					return "success";
				} else {
					if (flowByName != null) {
						return "false";
					} else {
						return "success";
					}
				}
			} else {
				if (flowByName != null) {
					return "false";
				} else {
					return "success";
				}
			}
		} else {
			if (flowByName != null) {
				return "false";
			} else {
				return "success";
			}
		}

	}

	/**
	 * 通过workId查找起草人
	 *
	 * @author 刘杰
	 * @date Aug 1, 2014 9:43:38 AM
	 * @param workId
	 * @return
	 */
	public String findStarterNameByWorkId(String workId) {
		return workDao.findStarterNameByWorkId(workId);
	}

	/**
	 * 根据参数判断是否有应用的权限
	 *
	 * @author zhangyong
	 * @date 2014-11-20 下午06:56:21
	 * @param app
	 * @param userId
	 * @param deptId
	 * @param roleId
	 * @return
	 */
	public boolean judgeIfHasAuthorityByApp(Application app, String userId, String deptId, String roleId) {
		boolean has = false;
		String appId = app.getAppId();
		List<AppAuthority>  authorityList  =  appAuthorityDao.findByAppId(appId);
		Map <String ,AppAuthority> authorityMap = new HashMap<String ,AppAuthority>();
		for(AppAuthority authority  :authorityList){
			authorityMap.put(authority.getAuthorityType(),authority);
		}
		AppAuthority appAuthority_per = authorityMap.get(AppAuthority.TYPE_PER);
		if (appAuthority_per != null && StringUtils.isNotBlank(appAuthority_per.getAuthorityData()) && StringUtils.isNotBlank(userId)) {
			String data_per = appAuthority_per.getAuthorityData();
			String[] dataArray_per = data_per.split(",");
			for (String d : dataArray_per) {
				if (d.equals(userId)) {
					has = true;
					break;
				}
			}
		}
		if (has == false) {
			AppAuthority appAuthority_dept = authorityMap.get(AppAuthority.TYPE_DEPT);
			if (appAuthority_dept != null && StringUtils.isNotBlank(appAuthority_dept.getAuthorityData()) && StringUtils.isNotBlank(deptId)) {
				String data_dept = appAuthority_dept.getAuthorityData();
				String[] dataArray_dept = data_dept.split(",");
				for (String d : dataArray_dept) {
					if (d.equals(deptId)) {
						has = true;
						break;
					}
				}
			}
		}
		if (has == false) {
			AppAuthority appAuthority_role = authorityMap.get(AppAuthority.TYPE_ROLE);
			if (appAuthority_role != null && StringUtils.isNotBlank(appAuthority_role.getAuthorityData()) && StringUtils.isNotBlank(roleId)) {
				String data_role = appAuthority_role.getAuthorityData();
				String[] dataArray_role = data_role.split(",");
				for (String d : dataArray_role) {
					if (d.equals(roleId)) {
						has = true;
						break;
					}
				}
			}
		}
		return has;
	}
	/**
	 * 查询待办的兄弟待办（同一个工作，同一个活动的其他待办）
	 * @author zhangyong
	 * @date   2014-11-27 下午05:04:56
	 * @param todoId
	 */
	public List<Todo> getOtherTodo(String todoId){
		Todo todo = todoDao.get(todoId);
		return todoDao.getOtherTodo(todoId, todo.getWorkId(), todo.getActivityName(),todo.getBatch());
	}

	/**
	 *  @Description    : 是否有某个操作权限对于待办(例如：保存、提交、删除、发布。。。)
	 *  @Method_Name    : hasOperateAuthorityForTodo
	 *  @param app
	 *  @param work
	 *  @param todo
	 *  @param fun
	 *  @return
	 *  @return         : boolean
	 *  @Creation Date  : 2015年3月11日 上午9:24:10
	 *  @version        : v1.00
	 *  @Author         : calonlan

	 *  @Update Date    : 2015年3月11日 上午9:24:10
	 *  @Update Author  : calonlan
	 */
	private boolean hasOperateAuthorityForTodo(Application app,Work work, Todo todo,String fun) {
		Form form = app.getForm();
		Object[] objs = new Object[] { app.getAppId(), work.getFlowId(), todo.getActivityName(), form.getFormId() };
		Control control = controlDao.getControlByObjects(objs);
		if(control!=null){
			String[][] menuItems = FormMenuDefin.getMenuItems(Application.APPATTR_FORM);
			for (int i = 0; i < menuItems.length; i++) {
				String[] item = menuItems[i];
				if(item[0].equals(fun)){
					return ControlUtils.getFunValue(String.valueOf(control.getFunctionControl().charAt(i)));
				}
			}
		}
		return false;
	}

	public List<WorkOpinion> findOpinionByWorkIdAndTodoId(String workId, String todoId) {
		return commentDao.findByWorkIdAndTodoId(workId, todoId);
	}


	public ExecutionService getExecutionService() {
		return executionService;
	}

	public void setExecutionService(ExecutionService executionService) {
		this.executionService = executionService;
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public HistoryService getHistoryService() {
		return historyService;
	}

	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	public RepositoryService getRepositoryService() {
		return repositoryService;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}

	public ProcessDefinitionQuery getProcessDefinitionQuery() {
		return processDefinitionQuery;
	}

	public void setProcessDefinitionQuery(
			ProcessDefinitionQuery processDefinitionQuery) {
		this.processDefinitionQuery = processDefinitionQuery;
	}

	public ApplicationDao getAppDao() {
		return appDao;
	}

	public void setAppDao(ApplicationDao appDao) {
		this.appDao = appDao;
	}

	public ActivityDao getActivityDao() {
		return activityDao;
	}

	public void setActivityDao(ActivityDao activityDao) {
		this.activityDao = activityDao;
	}

	public ActorDefinDetailDao getActorDefinDetailDao() {
		return actorDefinDetailDao;
	}

	public void setActorDefinDetailDao(ActorDefinDetailDao actorDefinDetailDao) {
		this.actorDefinDetailDao = actorDefinDetailDao;
	}

	public ActorDefinDetailDao getDetailDao() {
		return detailDao;
	}

	public void setDetailDao(ActorDefinDetailDao detailDao) {
		this.detailDao = detailDao;
	}

	public FormDao getFormDao() {
		return formDao;
	}

	public void setFormDao(FormDao formDao) {
		this.formDao = formDao;
	}

	public TodoDao getTodoDao() {
		return todoDao;
	}

	public void setTodoDao(TodoDao todoDao) {
		this.todoDao = todoDao;
	}

	public TodoVarDao getTodoVarDao() {
		return todoVarDao;
	}

	public void setTodoVarDao(TodoVarDao todoVarDao) {
		this.todoVarDao = todoVarDao;
	}

	public WorkDao getWorkDao() {
		return workDao;
	}

	public void setWorkDao(WorkDao workDao) {
		this.workDao = workDao;
	}

	public CommentDao getCommentDao() {
		return commentDao;
	}

	public void setCommentDao(CommentDao commentDao) {
		this.commentDao = commentDao;
	}

	public HistTodoDao getHistTodoDao() {
		return histTodoDao;
	}

	public void setHistTodoDao(HistTodoDao histTodoDao) {
		this.histTodoDao = histTodoDao;
	}

	public AppTypeDao getAppTypeDao() {
		return appTypeDao;
	}

	public void setAppTypeDao(AppTypeDao appTypeDao) {
		this.appTypeDao = appTypeDao;
	}

	public ControlDao getControlDao() {
		return controlDao;
	}

	public void setControlDao(ControlDao controlDao) {
		this.controlDao = controlDao;
	}

	public AttachmentDao getAttachmentDao() {
		return attachmentDao;
	}

	public void setAttachmentDao(AttachmentDao attachmentDao) {
		this.attachmentDao = attachmentDao;
	}

	public AppAuthorityDao getAppAuthorityDao() {
		return appAuthorityDao;
	}

	public void setAppAuthorityDao(AppAuthorityDao appAuthorityDao) {
		this.appAuthorityDao = appAuthorityDao;
	}

	public FlowDao getFlowDao() {
		return flowDao;
	}

	public void setFlowDao(FlowDao flowDao) {
		this.flowDao = flowDao;
	}

	public FlowDetailDao getFlowDetailDao() {
		return flowDetailDao;
	}

	public void setFlowDetailDao(FlowDetailDao flowDetailDao) {
		this.flowDetailDao = flowDetailDao;
	}

	public FieldDao getFieldDao() {
		return fieldDao;
	}

	public void setFieldDao(FieldDao fieldDao) {
		this.fieldDao = fieldDao;
	}


}
